﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Data.EntityClient;
using System.Data.SqlClient;
using System.ComponentModel;
using System.Net;
using System.IO;
using System.Web.Script.Serialization;
using System.Data.OleDb;

namespace Bolseye
{
    public class Support
    {

        public static BolseyeEnt GetDB()
        {
            var b = GetSqlConnectionString();

            //SqlCommand cmd = new SqlCommand();
            //cmd.Connection = new SqlConnection(b.ToString());
            //cmd.Connection.Open();
            //cmd.CommandText = "DELETE * FROM [Logs]";
            //int aff = cmd.ExecuteNonQuery();
            //cmd.Connection.Close();


            var b2 = new EntityConnectionStringBuilder();
            b2.Metadata = "res://*/BolseyeModel.csdl|res://*/BolseyeModel.ssdl|res://*/BolseyeModel.msl";
            b2.ProviderConnectionString = b.ToString();
            b2.Provider = "System.Data.SqlClient";

            var db = new Bolseye.BolseyeEnt(b2.ToString());

            return db;
        }



        private static SqlConnectionStringBuilder GetSqlConnectionString()
        {
            var b = new SqlConnectionStringBuilder();
            b.DataSource = @".\SQLEXPRESS";

            b.AttachDBFilename = Settings1.Default.DBPath;

            if (string.Equals(System.Net.Dns.GetHostName(), "FX8150", StringComparison.OrdinalIgnoreCase))
                b.AttachDBFilename = Settings1.Default.DBPathAgus;

            b.IntegratedSecurity = true;
            b.UserInstance = true;
            b.MultipleActiveResultSets = true;

            return b;
        }



        public static void CompactDB()
        {
            var conn = GetSqlConnectionString();

            /// SHRINKING THE MDF DATABASE.
            /// 
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = new SqlConnection(conn.ToString());
            cmd.Connection.Open();
            cmd.CommandText = "DBCC SHRINKDATABASE ( 0 ) ";
            int aff = cmd.ExecuteNonQuery();
            cmd.Connection.Close();

            //SqlCommand cmd = new SqlCommand();
            //cmd.Connection = new SqlConnection(b.ToString());
            //cmd.Connection.Open();
            //cmd.CommandText = "DELETE * FROM [Logs]";
            //int aff = cmd.ExecuteNonQuery();
            //cmd.Connection.Close();
        }



        public static float CalculateBuyingCost(bool precioLimite, float precioVenta, float cantidad)
        {
            return CalculateBuyingCost(precioLimite, precioVenta * cantidad);
        }

        public static float CalculateBuyingCost(bool precioLimite, float inversion)
        {
            float amount = (precioLimite) ? inversion * 0.06f : inversion * 0.1f;

            float iva = amount * 1.21f;

            return iva;
        }

        public static string ValueToPercent(double value)
        {
            return value.ToString("#,0.00") + " %";
        }


        public static string ValueToString(double value)
        {
            return ValueToString((float)value);
        }

        public static string ValueToString(float value)
        {
            return value.ToString("$#,0.00");
        }


        public static double CalcularVariacionDiaria(double cierreAnterior, double cierreActual)
        {
            return (cierreActual - cierreAnterior) * 100d / cierreActual;
        }

        public static void MarcarSimboloActualizado(int simboloID)
        {
            var db = GetDB();

            var simboloObj = (from s in db.Simbolos
                              where s.ID == simboloID
                              select s).FirstOrDefault();


            if (simboloObj == null)
                throw new NotSupportedException("No se encontro el simbolo que desea actualizar");

            simboloObj.UltimaActualizacion = DateTime.UtcNow;

            int aff = db.SaveChanges();

        }

        public static void GrabarRegistro(int code, string estado, string html, string link, string mensaje)
        {
            GrabarRegistro(code, 0, estado, html, link, mensaje);
        }

        public static void GrabarRegistro(int code, int subCode, string estado, string html, string link, string mensaje)
        {
            var db = GetDB();

            var prevLog = (from log in db.Logs
                           where log.Code == code && log.SubCode == subCode
                           orderby log.ID descending
                           select log).FirstOrDefault();

            if (prevLog != null)
            {
                if (prevLog.Estado == estado &&
                    prevLog.Html == html &&
                    prevLog.Link == link &&
                    prevLog.Mensaje == mensaje)
                {
                    prevLog.Ocurrencia = DateTime.UtcNow;

                    db.SaveChanges();
                    return;
                }
            }


            var l = new Log();
            l.Code = code;
            l.SubCode = subCode;
            l.Estado = estado;
            l.Html = html;
            l.Link = link;
            l.Mensaje = mensaje;
            l.Ocurrencia = DateTime.UtcNow;

            db.Logs.AddObject(l);

            int aff = db.SaveChanges();
        }


        public static int ObtenerIDdeSimbolo(BolseyeEnt db, string simbolo)
        {
            simbolo = (simbolo + "").Trim();

            var simbID = from s in db.Simbolos
                         where s.Simb == simbolo
                         select s.ID;

            if (simbID.Count() == 0) return -1;

            return simbID.First();
        }

        public static Simbolo ObtenerSimbolo(BolseyeEnt db, string simbolo)
        {
            simbolo = (simbolo + "").Trim();

            var simb = from s in db.Simbolos
                       where s.Simb == simbolo
                       select s;

            return simb.FirstOrDefault();
        }




        public static ResumenOperacion ObtenerResumenOperacion(int idOperacion)
        {
            var db = Support.GetDB();

            var compra = (
                            from o in db.Operaciones
                            where o.ID == idOperacion
                            select o
                         ).FirstOrDefault();

            if (compra == null)
                throw new NotSupportedException("La operacion solicitada no existe.");

            var simbolo = (
                            from s in db.Simbolos
                            where s.ID == compra.Simbolo
                            select s
                            ).FirstOrDefault();

            var ultimoTicker = (
                            from t in db.Tickers
                            where t.Simbolo == compra.Simbolo
                            orderby t.ID descending
                            select t
                        ).FirstOrDefault();

            double varAbs = ultimoTicker.Precio - compra.PcioVenta;
            double varRel = varAbs * 100 / compra.PcioVenta;

            double pcioIngreso = compra.PcioVenta;

            double diasDesdeCompra = DateTime.UtcNow.Subtract(compra.FechaCreacion).TotalDays;
            double mesesDesdeCompra = diasDesdeCompra / 30;

            double capitalActual = compra.Cantidad * ultimoTicker.Precio;

            double gciaBruta = capitalActual - compra.Capital;
            double costoSalida = Support.CalculateBuyingCost(true, (float)capitalActual);

            var resumen = new ResumenOperacion
            {
                PrecioCompra = pcioIngreso,
                PrecioActual = ultimoTicker.Precio,
                VariacionAbs = varAbs,
                VariacionRel = varRel,
                DiasDesdeCompra = diasDesdeCompra,
                MesesDesdeCompra = mesesDesdeCompra,
                TasaMensual = varRel / mesesDesdeCompra,
                CapitalActual = capitalActual,
                GananciaBruta = gciaBruta,
                CostoSalida = costoSalida,
                GananciaNeta = gciaBruta - costoSalida,

                OperacionObj = compra,
                UltimoTickerObj = ultimoTicker,
                SimboloObj = simbolo,
            };

            return resumen;
        }

        public static double ObtenerGananciaBruta(double cantidadAcciones, double precioAccion, double capitalInicial)
        {
            return ObtenerGananciaBruta(cantidadAcciones * precioAccion, capitalInicial);
        }

        public static double ObtenerGananciaBruta(double capitalActual, double capitalInicial)
        {
            return capitalActual - capitalInicial;
        }

        public class Historia
        {
            public DateTime Fecha;
            public double PrecioCierre;
            public double PrecioApertura;
            public double PrecioMin;
            public double PrecioMax;
        }


        public static List<Historia> ObtenerHistorialSimbolo(int simboloID)
        {
            var db = GetDB();

            var simbObj = (from s in db.Simbolos
                           where s.ID == simboloID
                           select s).FirstOrDefault();

            if (simbObj == null)
                throw new NotSupportedException("No se encontro el simbolo solicitada");

            var tickersObj = from t in db.Tickers
                             where t.Simbolo == simboloID
                             select t;

            var rval = new List<Historia>();

            tickersObj.ToList().ForEach(t =>
            {
                rval.Add(new Historia
                {
                    Fecha = t.Hora,
                    PrecioMin = t.Minimo,
                    PrecioMax = t.Maximo,
                    PrecioApertura = t.Apertura,
                    PrecioCierre = t.Cierre
                });
            });

            return rval;
        }


        public static List<Historia> ObtenerHistorialGananciaBruta(int operacionID)
        {
            var db = GetDB();

            var opObj = (from op in db.Operaciones
                         where op.ID == operacionID
                         select op).FirstOrDefault();

            if (opObj == null)
                throw new NotSupportedException("No se encontro la operacion solicitada");

            var tickersObj = from t in db.Tickers
                             where t.Simbolo == opObj.Simbolo
                             select t;

            var rval = new List<Historia>();

            tickersObj.ToList().ForEach(t =>
            {
                rval.Add(new Historia
                {
                    Fecha = t.Hora,
                    PrecioCierre = ObtenerGananciaBruta(opObj.Cantidad, t.Precio, opObj.Capital)
                });
            });

            return rval;

        }


        public static List<ResumenOperacionVerbose> ObtenerTodosLosResumenesTexto()
        {
            var db = GetDB();

            var o = from op in db.Operaciones
                    orderby op.ID descending
                    select op.ID;

            var resumenes = new List<ResumenOperacionVerbose>();

            o.ToList().ForEach(id =>
            {
                resumenes.Add(new ResumenOperacionVerbose(ObtenerResumenOperacion(id)));
            });

            return resumenes;
        }

        public static List<ResumenOperacion> ObtenerTodosLosResumenes()
        {
            var db = GetDB();

            var o = from op in db.Operaciones
                    orderby op.ID descending
                    select op.ID;

            var resumenes = new List<ResumenOperacion>();

            o.ToList().ForEach(id =>
            {
                resumenes.Add(ObtenerResumenOperacion(id));
            });

            return resumenes;
        }




        public class oo
        {
            public d[] d = new d[0];
        }



        public class d
        {
            public EspeciesSeries[] EspeciesSeries = new EspeciesSeries[0];
        }


        public class EspeciesSeries
        {
            public int Hora;
            public double PrecioUltimo;
            public double TipoSerie;
            public double VolumenNominal;
            public string Simbolo;
            public DateTime Fecha;
            public double EspecieID;
            public double MercadoSiuID;
            public double Vencimiento;
            public double TipoGarantiaSiuID;
            public double CategoriaSiuID;
            public double TipoLiquidacionSiuID;
                        public double PrecioMaximo;
            public double PrecioMinimo;
            public double PrecioPromedio;
            public double PrecioCierre;

            public double VariacionPrecio;
            public double TotalOperadoVn;
            public double TotalOperadoMonto;
            public double Operaciones;
            public double PrecioAperturaHomogeneo;
            public double PrecioMaximoHomogeneo;
            public double PrecioMinimoHomogeneo;
            public double PrecioPromedioHomogeneo;
            public double PrecioCierreHomogeneo;
            public double TotalOperadoVnHomogeneo;
        }



        class Sape
        {
            public  string Simbolo;
            public DateTime Fecha;
            public double Apertura;
            public double Cierre;
            public double Minimo;
            public double Maximo;
        }




        public static void ParseTextFiles2()
        {
            var query = "select * from file.dat";
var connection = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Garzon\Development\Bolseye\DBProject\Cotiz_Pack\F1.DAT;Extended Properties=""text;HDR=NO;FMT=FixedLength""");

OleDbCommand cmd = new OleDbCommand(query);
cmd.Connection = connection;

 int aff = cmd.ExecuteNonQuery();

 return;
            byte[] results = File.ReadAllBytes(@"C:\Garzon\Development\Bolseye\DBProject\Cotiz_Pack\F1.DAT");

            var str = BitConverter.ToString(results);
        }


        public static void ParseTextFiles()
        {
            var sapes = new List<Sape>();

            DirectoryInfo dir = new DirectoryInfo(@"C:\Garzon\Development\Bolseye\DBProject\Cotiz_Pack");

            foreach (var file in dir.GetFiles("*.txt"))
            {
                string[] lines = File.ReadAllLines(file.FullName);

                lines.Skip(1).ToList().ForEach(l =>
                {
                    string[] parts = l.Split(new string[] { "," }, StringSplitOptions.None);

                    string date = parts[1].Trim();

                    int Y = int.Parse(date.Substring(0, 2));
                    int M = int.Parse(date.Substring(2, 2));
                    int D = int.Parse(date.Substring(4, 2));

                    Sape s = new Sape
                    {
                        Simbolo = parts[0],
                        Fecha = new DateTime(Y, M, D),
                        Apertura = double.Parse(parts[2]),
                        Cierre = double.Parse(parts[5]),
                        Maximo = double.Parse(parts[3]),
                        Minimo = double.Parse(parts[4]),
                    };

                    sapes.Add(s);
                
                });

            }

        }



        public static void ParseNewThingy()
        {
//            string s = @"{""d"":
//
//[{""EspeciesSeries"":
//
//[{""Hora"":170000,""PrecioUltimo"":79,""TipoSerie"":0,""VolumenNominal"":1,""Simbolo"":""YPFD"",
//""Fecha"":""\/Date(1349406000000)\/"",""EspecieID"":-1,""MercadoSiuID"":1,""Vencimiento"":4,
//""TipoGarantiaSiuID"":1,""CategoriaSiuID"":1,""TipoLiquidacionSiuID"":0,""PrecioApertura"":79.65,
//""PrecioMaximo"":79.70,""PrecioMinimo"":78.75,""PrecioPromedio"":-1,
//""PrecioCierre"":79,""VariacionPrecio"":-0.5040,""TotalOperadoVn"":42384,""TotalOperadoMonto"":3362236,
//""Operaciones"":151,""PrecioAperturaHomogeneo"":-1,""PrecioMaximoHomogeneo"":-1,""PrecioMinimoHomogeneo"":-1,
//""PrecioPromedioHomogeneo"":-1,""PrecioCierreHomogeneo"":-1,""TotalOperadoVnHomogeneo"":-1},
//
//{""Hora"":170000,""PrecioUltimo"":79,""TipoSerie"":0,""VolumenNominal"":335,""Simbolo"":""YPFD"",""Fecha"":""\/Date(1349406000000)\/"",""EspecieID"":-1,""MercadoSiuID"":1,""Vencimiento"":4,""TipoGarantiaSiuID"":1,""CategoriaSiuID"":1,""TipoLiquidacionSiuID"":0,""PrecioApertura"":79.65,""PrecioMaximo"":79.70,""PrecioMinimo"":78.75,""PrecioPromedio"":-1,""PrecioCierre"":79,""VariacionPrecio"":-0.5040,""TotalOperadoVn"":42383,""TotalOperadoMonto"":3362157,""Operaciones"":150,""PrecioAperturaHomogeneo"":-1,""PrecioMaximoHomogeneo"":-1,""PrecioMinimoHomogeneo"":-1,""PrecioPromedioHomogeneo"":-1,""PrecioCierreHomogeneo"":-1,""TotalOperadoVnHomogeneo"":-1}
//
//]}
//
//]}
//";


//            var ddd = new d();

//            var es = new EspeciesSeries();
//            es.Hora = 15;

//            var esB = new EspeciesSeries();
//            esB.Hora = 17;

//            ddd.EspeciesSeries = new EspeciesSeries[2];
//            ddd.EspeciesSeries[0] = es;
//            ddd.EspeciesSeries[1] = esB;


//            JavaScriptSerializer des = new JavaScriptSerializer();

//            string outputt = des.Serialize(ddd);

//            var didi = des.Deserialize < oo>(s);

//        }

//        private static void Dooda()
//        {

            var req = (HttpWebRequest)HttpWebRequest.Create("http://nuevo.bolsar.com/VistasDL/PaginaIntradiarioEspecies.aspx/GetIntradiarioHistorico");
            req.Method = "POST";
            req.Headers.Add("Origin", "http://nuevo.bolsar.com");
            req.KeepAlive = true;
            req.Host = "nuevo.bolsar.com";
            req.UserAgent = "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4";
            req.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");
            req.ContentType = "application/json; charset=UTF-8";
            req.Referer = "http://nuevo.bolsar.com/VistasDL/PaginaIntradiarioEspecies.aspx?Especie=YPFD&Vto=4";

            req.CookieContainer = new CookieContainer();

            Cookie c = new Cookie();
            c.Name = "ASP.NET_SessionId";
            c.Value = "kb1e13qr1bgydk3i1f3fpeyd";
            c.Secure = false;
            c.HttpOnly = false;
            c.Domain = "bolsar.com";
            //c.Expires = false;

            req.CookieContainer.Add(c);

            using (StreamWriter sw = new StreamWriter(req.GetRequestStream()))
            {
                sw.Write("{\"strEspecie\":\"YPFD\",\"intVto\":\"4\",\"intPeriodoId\":4}");
                sw.Flush();
            }

            var resp = (HttpWebResponse)req.GetResponse();

            var sr = new StreamReader(resp.GetResponseStream());

            string output = sr.ReadToEnd();

            var s = new JavaScriptSerializer();
            s.MaxJsonLength = int.MaxValue;
            var dd = s.Deserialize<oo>(output);

        }

    }


    public class ResumenOperacionVerbose : Component
    {
        public ResumenOperacionVerbose(ResumenOperacion resumen)
        {
            this.TasaMensualDbl = resumen.TasaMensual;
            this.OpID = resumen.OperacionObj.ID;
            this.Simbolo = resumen.SimboloObj.Simb.ToUpper();
            this.VariacioAbs = Support.ValueToString( resumen.VariacionAbs);
            this.VariacionRel = Support.ValueToPercent(resumen.VariacionRel);
            this.PrecioCompra = Support.ValueToString(resumen.PrecioCompra);
            this.PrecioActual = Support.ValueToString(resumen.PrecioActual);
            this.DiasDesdeCompra = Support.ValueToString(resumen.DiasDesdeCompra);
            this.TasaMensual = Support.ValueToPercent(resumen.TasaMensual);
            this.CapitalIngreso = Support.ValueToString(resumen.OperacionObj.Capital);
            this.CapitalActual = Support.ValueToString(resumen.CapitalActual);
            this.GananciaBruta = Support.ValueToString(resumen.GananciaBruta);
            this.CostoEgreso = Support.ValueToString(resumen.CostoSalida);
            this.GananciaNeta = Support.ValueToString(resumen.GananciaNeta);
        }


        public string VariacioAbs { get; set; }

        public string VariacionRel { get; set; }

        public string PrecioCompra { get; set; }

        public string PrecioActual { get; set; }

        public string DiasDesdeCompra { get; set; }

        public string TasaMensual { get; set; }

        public string CapitalActual { get; set; }

        public string GananciaBruta { get; set; }

        public string CostoEgreso { get; set; }

        public string GananciaNeta { get; set; }

        public string Simbolo { get; set; }

        public string CapitalIngreso { get; set; }

        public int OpID { get; set; }

        public double TasaMensualDbl { get; set; }
    }


    public class ResumenOperacion : Component
    {
        public double VariacionAbs { get; set; }

        public double PrecioCompra { get; set; }

        public double PrecioActual { get; set; }

        public double VariacionRel { get; set; }

        public double DiasDesdeCompra { get; set; }

        public double MesesDesdeCompra { get; set; }

        public double TasaMensual { get; set; }

        public Operacion OperacionObj { get; set; }

        public Ticker UltimoTickerObj { get; set; }

        public Simbolo SimboloObj { get; set; }

        public double CapitalActual { get; set; }

        public double GananciaBruta { get; set; }
        
        public double GananciaNeta { get; set; }

        public double CostoSalida { get; set; }
    }
}
